package com.gitee.feizns.quickstart.domain.query;

import com.gitee.feizns.dynamic.Nums;
import com.gitee.feizns.dynamic.bean.Props;
import com.gitee.feizns.quickstart.domain.page.DollarPageAo;
import com.gitee.feizns.quickstart.domain.page.PageAo;
import com.gitee.feizns.quickstart.jackson.Val;

import java.util.Map;

/**
 * 查询请求参数
 * @author feizns
 * @since 2025/6/14
 */
public interface QueryAo {

    /**
     * 分页参数
     * 解析
     *  $current    为页码
     *  $size       为每页条数
     * @return {@link PageAo }
     */
    default PageAo page() {
        Map<String, Object> params = params();
        DollarPageAo ao = new DollarPageAo();
        Number current = Nums.of(params.get("$current"));
        if ( current != null )
            ao.set$current(current.longValue());
        Number size = Nums.of(params.get("$size"));
        if ( size != null )
            ao.set$size(size.longValue());
        Number limit = Nums.of(params.get("$limit"));
        if ( limit != null )
            ao.set$limit(limit.longValue());
        return ao;
    }

    /**
     * 查询参数
     * 构建自定义查询条件
     * <pre>
     * {@code
     *      //字段操作符查询
     *      //等值
     *      $eq：              （id = 5）                            （{"id":5}或者{"id":{"$eq":5}}）
     *      //不等
     *      $ne：              （id != 5）                           （{"id":{"$ne":5}}）
     *      //大于
     *      $gt：              （id > 5）                            （{"id":{"$gt":5}}）
     *      //大于等于
     *      $ge：              （id >= 5）                           （{"id":{"$ge":5}}）
     *      //小于
     *      $lt：              （id < 5）                            （{"id":{"$lt":5}}）
     *      //小于等于
     *      $le：              （id <= 5）                           （{"id":{"$le":5}}）
     *      //匹配值在指定序列中
     *      $in：              （id IN (5,6)）                       （{"id":{"$in":[5, 6]}}）
     *      //字符串匹配（包含）
     *      $contains：        （name LIKE ('%', 'hpp','%')）        （{"name":{"$contains":"hhp"}}）
     *      //字符串匹配（左边包含）
     *      $startWith：       （name LIKE ('hpp','%')）            （{"name":{"$startWith":"hhp"}}）
     *      //字符串匹配（右边包含）
     *      $endWith：         （name LIKE ('%', 'hpp')）            （{"name":{"$endWith":"hhp"}}）
     *      //数值或时间区间
     *      $between：         （id BETWEEN 5 AND 10）               （{"id":{"$between":[5, 10]}}）
     *      //正则表达式匹配
     *      $regexp：          （name REGEXP 'hhp$'）                （{"name":{"$regexp":"hhp$"}}）
     *
     *      //json列查询（JSON_UNQUOTE(JSON_EXTRACT(user_list, '$.id')) = 5）
     *      {"userList$.id": 5}
     *
     *      //其他设置：
     *      //设置查询字段（SELECT id, name）
     *      $select：        {"$select":["id", "name"]}
     *      //设置查询的表（FROM user）
     *      $from：          {"$from":"user"}
     *      //多个and嵌套条件（id = 1 AND name = 'hhp'）
     *      $and：           {"$and": [{"id":1}, {"name":"hhp"}]}
     *      //多个not嵌套条件（id = 1 OR name = 'hhp'）
     *      $not：           {"$not": [{"id":1}, {"name":"hhp"}]}
     *      //多个or嵌套条件（NOT (id = 1 AND name = 'hhp')）
     *      $or：            {"$or": [{"id":1}, {"name":"hhp"}]}
     *      //多个字段排序规则（ORDER BY create_time ASC, name DESC）
     *      $order：         {"$order": [{"column":"createTime", "asc":"true"}, {"column":"name"}]}
     *      //多字段升序（ORDER BY id ASC, name ASC）
     *      $asc：           {"$asc":["id", "name"]}
     *      //多字段逆序（ORDER BY id DESC, name DESC）
     *      $desc：          {"$desc":["id", "name"]}
     *      //构建多字段分组（GROUP BY id, name）
     *      $group：         {"$group":["id", "name"]}
     *      //筛选是否为NULL（id IS NULL AND name is NULL）
     *      $null：          {"$null":["id", "name"]}
     *      //偏移查询（LIMIT 10, 10）
     *      $offset、$limit：{"$offset":10, "$limit":10}
     *      //多字段连接查询（CONCAT_WS('', id, name) LIKE CONCAT('%','hhp','%')）
     *      $keyword：       {"$keyword":{"columns":["id", "name"], operator: "$likeLeft", "value":"hhp"}}
     * }
     * </pre>
     * @return {@link Map }<{@link String }, {@link Object }>
     */
    Map<String, Object> params();

    /**
     * 参数
     * @param key 钥匙
     * @return {@link Val }
     */
    default Val param(String key) {
        return Val.of(params().get(key));
    }

    /**
     * 提取键的值并删除该键值
     * @param key 钥匙
     * @return {@link Val }
     */
    Val pluck(String key);

    /**
     * 忽略的参数
     * @param ignoreKeys 忽略键
     * @return {@link Map }<{@link String }, {@link Object }>
     */
    default Map<String, Object> omit(String... ignoreKeys) {
        Map<String, Object> params = params();
        if ( ignoreKeys != null ) {
            for ( String key : ignoreKeys )
                params.remove(key);
        }
        return params;
    }

    /**
     * 省略
     * @param ignoreKeysOfClassProps 忽略类属性
     * @return {@link Map }<{@link String }, {@link Object }>
     */
    default Map<String, Object> omit(Class<?> ignoreKeysOfClassProps) {
        return omit(Props.names(ignoreKeysOfClassProps).toArray(String[]::new));
    }

}
